using System;
using Tarkin.InfrastructureLibrary.Core.Basic;
using Tarkin.InfrastructureLibrary.Core.PrimitiveTypes;
using Tarkin.InfrastructureLibrary.Tests.Core.Basic.TestUtilities.ConcreteClasses;
using NUnit.Framework;

namespace Tarkin.InfrastructureLibrary.Tests.Core.Basic
{
    /// <summary>
    /// PropertyTests is the NUnit TestFixture for the Tarkin.InfrastructureLibrary.Core.Basic.Property class.
    /// </summary>
    [TestFixture]
    public class PropertyTests
    {

        [Test]
        public void TestOverloadedConstructorOneParameter ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "TypedElement Name" );
            Property property = new Property ( typedElement );

            Assert.IsNotNull ( property );
            Assert.AreEqual ( "TypedElement Name", property.Name );
        }

        [Test]
        [ExpectedException ( typeof ( ArgumentNullException ) )]
        public void TestOverloadedConstructorOneParameterNullValue ()
        {
            Property property = new Property ( null );
        }

        [Test]
        public void TestOverloadedConstructorTwoParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "TypedElement Name" );
            UnlimitedNatural unlimitedNatural = new UnlimitedNatural ( UnlimitedNatural.UnlimitedNaturalInfinity );
            ConcreteMultiplicityElement multiplicityElement = new ConcreteMultiplicityElement ( true, true, 0, unlimitedNatural );
            Property property = new Property ( typedElement, multiplicityElement );

            Assert.IsNotNull ( property );
            Assert.AreEqual ( "TypedElement Name", property.Name );
            Assert.AreEqual ( true, property.IsOrdered );
            Assert.AreEqual ( true, property.IsUnique );
            Assert.AreEqual ( 0, property.Lower );
            Assert.AreEqual ( UnlimitedNatural.UnlimitedNaturalInfinity, property.Upper.Value );
        }

        [Test]
        public void TestOverloadedConstructorFiveParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "TypedElement Name" );
            UnlimitedNatural unlimitedNatural = new UnlimitedNatural ( UnlimitedNatural.UnlimitedNaturalInfinity );
            Property property = new Property ( typedElement, false, false, 23, unlimitedNatural );

            Assert.IsNotNull ( property );
            Assert.AreEqual ( "TypedElement Name", property.Name );
            Assert.AreEqual ( false, property.IsOrdered );
            Assert.AreEqual ( false, property.IsUnique );
            Assert.AreEqual ( 23, property.Lower );
            Assert.AreEqual ( UnlimitedNatural.UnlimitedNaturalInfinity, property.Upper.Value );
        }

        [Test]
        public void TestOverloadedConstructorEightParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "TypedElement Name" );
            UnlimitedNatural unlimitedNatural = new UnlimitedNatural ( UnlimitedNatural.UnlimitedNaturalInfinity );
            ConcreteMultiplicityElement multiplicityElement = new ConcreteMultiplicityElement ( true, true, 0, unlimitedNatural );
            Class owningClass = new Class ( "OwningClass name" );
            Property oppositeProperty = new Property ( typedElement );
            Property property = new Property ( typedElement, multiplicityElement, owningClass, "Default value", true, false, true, oppositeProperty );

            Assert.IsNotNull ( property );
            Assert.AreEqual ( "TypedElement Name", property.Name );
            Assert.AreEqual ( true, property.IsOrdered );
            Assert.AreEqual ( true, property.IsUnique );
            Assert.AreEqual ( 0, property.Lower );
            Assert.AreEqual ( UnlimitedNatural.UnlimitedNaturalInfinity, property.Upper.Value );
            Assert.AreEqual ( owningClass, property.Class );
            Assert.AreEqual ( "Default value", property.Default );
            Assert.IsTrue ( property.IsComposite );
            Assert.IsFalse ( property.IsDerived );
            Assert.IsTrue ( property.IsReadOnly );
            Assert.AreEqual ( oppositeProperty, property.Opposite );
        }

        [Test]
        public void TestNameProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "TypedElement Name" );
            Property property = new Property ( typedElement );

            property.Name = "Some other name";

            Assert.AreEqual ( "Some other name", property.Name );
        }

        [Test]
        public void TestTypeProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "TypedElement Name" );
            Property property = new Property ( typedElement );
            ConcreteType type = new ConcreteType ( "Some Type" );

            property.Type = type;

            Assert.AreEqual ( "Some Type", property.Type.Name );
        }
    }
}
